
define(["_", "./events", "./dom", "./builder", "./utils", "./forms"], function(_, events, dom, builder, utils) {
  var collectOptionValues, createHelpBlock, ensureFieldId, exports, findHelpBlock, showValidationError;
  ensureFieldId = function(field) {
    var fieldId;
    fieldId = field.attribute("id");
    if (!fieldId) {
      fieldId = _.uniqueId("field");
      field.attribute("id", fieldId);
    }
    return fieldId;
  };
  findHelpBlock = function(field) {
    var block, fieldId, group;
    fieldId = field.attribute("id");
    if (fieldId) {
      block = dom.body().findFirst("[data-error-block-for='" + fieldId + "']");
      if (block) {
        return block;
      }
    } else {
      fieldId = ensureFieldId(field);
    }
    group = field.findParent(".controls, .control-group");
    if (!group) {
      return null;
    }
    block = group.findFirst("[data-presentation=error]");
    if (block) {
      if (!fieldId) {
        fieldId = _.uniqueId("field");
        field.attribute("id", fieldId);
      }
      block.attribute("data-error-block-for", fieldId);
    }
    return block;
  };
  createHelpBlock = function(field) {
    var block, container, fieldId;
    fieldId = ensureFieldId(field);
    container = field.parent();
    block = builder("p.help-block", {
      "data-error-block-for": fieldId
    });
    if (container.hasClass("input-append") || container.hasClass("input-prepend")) {
      container.insertAfter(block);
    } else {
      field.insertAfter(block);
    }
    return block;
  };
  showValidationError = function(id, message) {
    return dom.wrap(id).trigger(events.field.showValidationError, {
      message: message
    });
  };
  collectOptionValues = function(wrapper) {
    return _.pluck(wrapper.element.options, "value");
  };
  dom.onDocument(events.field.inputValidation, function(event, formMemo) {
    var failure, fieldValue, memo, postEventTrigger,
      _this = this;
    if (!this.deepVisible()) {
      return;
    }
    failure = false;
    fieldValue = (this.attribute("data-value-mode")) === "options" ? collectOptionValues(this) : this.value();
    memo = {
      value: fieldValue
    };
    postEventTrigger = function() {
      if (memo.error) {
        failure = true;
        if (_.isString(memo.error)) {
          return _this.trigger(events.field.showValidationError, {
            message: memo.error
          });
        }
      }
    };
    this.trigger(events.field.optional, memo);
    postEventTrigger();
    if (!(failure || (utils.isBlank(memo.value)))) {
      this.trigger(events.field.translate, memo);
      postEventTrigger();
      if (!failure) {
        if (_.isUndefined(memo.translated)) {
          memo.translated = memo.value;
        }
        this.trigger(events.field.validate, memo);
        postEventTrigger();
      }
    }
    if (failure) {
      formMemo.error = true;
    } else {
      this.trigger(events.field.clearValidationError);
    }
  });
  dom.onDocument(events.field.clearValidationError, function() {
    var block, group;
    block = exports.findHelpBlock(this);
    if (block) {
      block.hide().update("");
    }
    group = this.findParent(".control-group");
    group && group.removeClass("error");
  });
  dom.onDocument(events.field.showValidationError, function(event, memo) {
    var block, group;
    block = exports.findHelpBlock(this);
    if (!block) {
      block = exports.createHelpBlock(this);
    }
    block.show().update(memo.message);
    group = this.findParent(".control-group");
    return group && group.addClass("error");
  });
  return exports = {
    findHelpBlock: findHelpBlock,
    createHelpBlock: createHelpBlock,
    showValidationError: showValidationError
  };
});
